home *** CD-ROM | disk | FTP | other *** search
/ NOVA - For the NeXT Workstation / NOVA - For the NeXT Workstation.iso / SourceCode / AdobeExamples / NX_ImportAdv / NXEPSImageRepSub.m < prev    next >
Text File  |  1992-12-19  |  12KB  |  519 lines

  1.  
  2. /*
  3.  * (a)  (C) 1990 by Adobe Systems Incorporated. All rights reserved.
  4.  *
  5.  * (b)  If this Sample Code is distributed as part of the Display PostScript
  6.  *    System Software Development Kit from Adobe Systems Incorporated,
  7.  *    then this copy is designated as Development Software and its use is
  8.  *    subject to the terms of the License Agreement attached to such Kit.
  9.  *
  10.  * (c)  If this Sample Code is distributed independently, then the following
  11.  *    terms apply:
  12.  *
  13.  * (d)  This file may be freely copied and redistributed as long as:
  14.  *    1) Parts (a), (d), (e) and (f) continue to be included in the file,
  15.  *    2) If the file has been modified in any way, a notice of such
  16.  *      modification is conspicuously indicated.
  17.  *
  18.  * (e)  PostScript, Display PostScript, and Adobe are registered trademarks of
  19.  *    Adobe Systems Incorporated.
  20.  * 
  21.  * (f) THE INFORMATION BELOW IS FURNISHED AS IS, IS SUBJECT TO
  22.  *    CHANGE WITHOUT NOTICE, AND SHOULD NOT BE CONSTRUED
  23.  *    AS A COMMITMENT BY ADOBE SYSTEMS INCORPORATED.
  24.  *    ADOBE SYSTEMS INCORPORATED ASSUMES NO RESPONSIBILITY
  25.  *    OR LIABILITY FOR ANY ERRORS OR INACCURACIES, MAKES NO
  26.  *    WARRANTY OF ANY KIND (EXPRESS, IMPLIED OR STATUTORY)
  27.  *    WITH RESPECT TO THIS INFORMATION, AND EXPRESSLY
  28.  *    DISCLAIMS ANY AND ALL WARRANTIES OF MERCHANTABILITY, 
  29.  *    FITNESS FOR PARTICULAR PURPOSES AND NONINFRINGEMENT
  30.  *    OF THIRD PARTY RIGHTS.
  31.  */
  32.  
  33. /*
  34.  *    NXEPSImageRepSub.m
  35.  *
  36.  *    A subclass of NXEPSImageRep. Enhanced to handle rotation
  37.  *    and resources.
  38.  *
  39.  *    Version:    2.0
  40.  *    Author:    Ken Fromm
  41.  */
  42.  
  43. #import "NXEPSImageRepSub.h"
  44.  
  45. #import <appkit/Font.h>
  46. #import <appkit/Panel.h>
  47. #import <appkit/View.h>
  48. #import <appkit/nextstd.h>
  49. #import <appkit/defaults.h>
  50.  
  51. #import <objc/List.h>
  52. #import <objc/Storage.h>
  53. #import <objc/hashtable.h>
  54. #import <dpsclient/wraps.h>
  55. #import <stdio.h>
  56.  
  57. /*    Used only for demonstration purposes. */
  58. #import "ImportApp.h"
  59. #import "epsfwraps.h"
  60.  
  61. @implementation NXEPSImageRepSub
  62.  
  63. - free
  64. {
  65.     if (_tempName)
  66.         NX_FREE(_tempName);
  67.  
  68.     return [super  free];
  69. }
  70.  
  71. - writeIncludedFiles:storage;
  72. {
  73.     int            i, count,
  74.                 writelen, readlen, includelen, maxlen;
  75.  
  76.     char            *readdata, *startdata, *includedata;
  77.  
  78.     NXStream    *writestream, *readstream, *includestream;
  79.  
  80.     Inclusion        *inclusion;
  81.  
  82.     if (storage && [storage  count])
  83.     {
  84.         readlen = 0;    
  85.         readdata = NULL;
  86.         readstream = NULL;
  87.         if (_fileName)
  88.         {
  89.             readstream = NXMapFile(_fileName, NX_READONLY);
  90.             if (readstream)
  91.                 NXGetMemoryBuffer(readstream, &readdata, &readlen, &maxlen);
  92.         }
  93.         else
  94.         {
  95.             readdata = _memory;
  96.             readlen = _epsLen;
  97.         }
  98.  
  99.         if (readdata && readlen)
  100.         { 
  101.             startdata = readdata;
  102.             if (_fileName)
  103.                 writestream = NXOpenMemory(NULL, 0, NX_WRITEONLY);
  104.             else
  105.                 writestream = NXOpenMemory(NULL, 0, NX_READWRITE);
  106.             if (writestream)
  107.             {
  108.                 count = [storage  count];
  109.                 for (i = 0; i < count; i++)
  110.                 {
  111.                     inclusion = [storage  elementAt:i];
  112.                     if (inclusion->filename && inclusion->len)
  113.                     {
  114.                         writelen = inclusion->offset - (readdata - startdata);
  115.                         NXWrite(writestream, readdata, writelen);
  116.                         includestream = NXMapFile(inclusion->filename, NX_READONLY);
  117.                         if (includestream)
  118.                         {
  119.                             NXGetMemoryBuffer(includestream, &includedata,
  120.                                 &includelen, &maxlen);
  121.                             NXWrite(writestream, includedata, includelen);
  122.                         }
  123.                         else
  124.                             NXWrite(writestream, readdata+inclusion->offset,
  125.                                         inclusion->len);
  126.                         readdata += writelen + inclusion->len;
  127.                         readlen -= (writelen + inclusion->len);
  128.                     }
  129.                 }
  130.                 NXWrite(writestream, readdata, readlen);
  131.  
  132.                 if (_fileName)
  133.                 {
  134.                     _tempName = NXCopyStringBuffer("/tmp/EpsfTempXXXXXX.eps");
  135.                     NXGetTempFilename(_tempName, 13);
  136.                     if (_tempName)
  137.                         NXSaveToFile(writestream, _tempName);
  138.                     NXCloseMemory(writestream, NX_FREEBUFFER);
  139.                 }
  140.                 else
  141.                 {
  142.                     NXGetMemoryBuffer(writestream, &_tempMemory,
  143.                                 &_tempEpsLen, &maxlen);
  144.                     NXCloseMemory(writestream, NX_SAVEBUFFER);
  145.                 }
  146.             }
  147.         }
  148.  
  149.         if (readstream)
  150.             NXCloseMemory(readstream, NX_FREEBUFFER);
  151.     }
  152.  
  153.     return self;
  154. }
  155.  
  156. /*
  157. *    Check to see if the fonts are on the system and only flag
  158. *    those not available.
  159. */
  160. - checkFonts:(Resource *) resource  placeIn:(ResourceList *) resourceList
  161. {
  162.     id            font;
  163.  
  164.     int            i, count;
  165.  
  166.     if (resource && resourceList)
  167.     {
  168.         if (resource->states[RES_NEEDED])
  169.             resourceList->types[RES_FONTS] = [resource->states[RES_NEEDED]  copy];
  170.         else if (!resource->states[RES_SUPPLIED] && resource->states[RES_PRESENT])
  171.             resourceList->types[RES_FONTS] = [resource->states[RES_PRESENT]  copy];
  172.  
  173.         /*
  174.         *    There should be an easier way to check for font availability other
  175.         *    than to create a font object but this will have to do for now.
  176.         */
  177.         count = [resourceList->types[RES_FONTS]  count];
  178.         for (i = count -1; i >= 0; i--)
  179.         {
  180.             font = [Font  newFont:(char *) [resourceList->types[RES_FONTS]  objectAt:i]  size:12];
  181.             if (font)
  182.             {
  183.                 [font  free];
  184.                 [resourceList->types[RES_FONTS]  removeObjectAt:i];
  185.             }
  186.         }
  187.  
  188.         if ([resourceList->types[RES_FONTS]  count] == 0)
  189.         {
  190.             [resourceList->types[RES_FONTS]  free];
  191.             resourceList->types[RES_FONTS] = NULL;
  192.         }
  193.     }
  194.  
  195.     return self;
  196. }
  197.  
  198. - checkFiles:(Resource *) resource  placeIn:(ResourceList *) resourceList
  199. {
  200.     int        i, count;
  201.  
  202.     FILE        *file;
  203.  
  204.     if (resource && resourceList)
  205.     {
  206.         if (resource->states[RES_NEEDED])
  207.             resourceList->types[RES_FILES] = [resource->states[RES_NEEDED]  copy];
  208.  
  209.         /*
  210.         *    Try to open the files. If available then remove from the list.
  211.         */
  212.         count = [resourceList->types[RES_FILES]  count];
  213.         for (i = count -1; i >= 0; i--)
  214.         {
  215.             file = fopen((char *) [resourceList->types[RES_FILES]  objectAt:i], "r");
  216.             if (file)
  217.             {
  218.                 fclose(file);
  219.                 [resourceList->types[RES_FILES]  removeObjectAt:i];
  220.             }
  221.         }
  222.  
  223.         if ([resourceList->types[RES_FILES]  count] == 0)
  224.         {
  225.             [resourceList->types[RES_FILES]  free];
  226.             resourceList->types[RES_FILES] = NULL;
  227.         }
  228.     }
  229.  
  230.     return self;
  231. }
  232.  
  233. - checkProcSets:(Resource *) resource  placeIn:(ResourceList *) resourceList
  234. {
  235.     if (resource && resourceList)
  236.     {
  237.         if (resource->states[RES_NEEDED])
  238.             resourceList->types[RES_PROCSETS] = [resource->states[RES_NEEDED]  copy];
  239.     }
  240.  
  241.     return self;
  242. }
  243.  
  244. - checkPatterns:(Resource *) resource  placeIn:(ResourceList *) resourceList
  245. {
  246.     if (resource && resourceList)
  247.     {
  248.         if (resource->states[RES_NEEDED])
  249.             resourceList->types[RES_PATTERNS] = [resource->states[RES_NEEDED]  copy];
  250.     }
  251.  
  252.     return self;
  253. }
  254.  
  255. - checkForms:(Resource *) resource  placeIn:(ResourceList *) resourceList
  256. {
  257.     if (resource && resourceList)
  258.     {
  259.         if (resource->states[RES_NEEDED])
  260.             resourceList->types[RES_FORMS] = [resource->states[RES_NEEDED]  copy];
  261.     }
  262.  
  263.     return self;
  264. }
  265.  
  266. /*
  267. *    Fills in the empty resources and inclusions array within the epsf structure. 
  268. */
  269. - (int) getResources:(EpsfStruct *) epsf
  270. {
  271.     int            maxlen, error;
  272.  
  273.     NXStream    *stream;
  274.  
  275.     error = EPSF_INVALIDPS;
  276.     if (epsf)
  277.     {
  278.         stream = NULL;
  279.         epsf->filedata = NULL;
  280.         if (_fileName)
  281.         {
  282.             stream = NXMapFile(_fileName, NX_READONLY);
  283.             if (stream)
  284.                 NXGetMemoryBuffer(stream, &epsf->filedata, &epsf->filelen, &maxlen);
  285.         }
  286.         else
  287.         {
  288.             epsf->filedata = _memory;
  289.             epsf->filelen = _epsLen;
  290.         }
  291.             
  292.         if (epsf->filedata)
  293.             error = ReadEpsf(epsf);
  294.  
  295.         if (stream)
  296.             NXCloseMemory(stream, NX_FREEBUFFER);
  297.     }    
  298.     
  299.     return error;
  300. }
  301.  
  302. /*
  303. *    Returns the list of unavailableResources.
  304. *
  305. *    Returns any resources except for fonts that are marked as needed.
  306. *    Check to see if the fonts are on the system and flags only those not
  307. *    available. As the other resources move into the realm of system
  308. *    resources, this method can check the availability of these resources
  309. *    as well.
  310. *
  311. */
  312. - checkResources:(ResourceList *) resourceList;
  313. {
  314.     int            error;
  315.  
  316.     EpsfStruct    epsf;
  317.  
  318.     bzero(resourceList, sizeof(ResourceList));
  319.     error = [self  getResources:&epsf];
  320.     if (!error)
  321.     {
  322.         [self  checkFonts:&epsf.resources[RES_FONTS]  placeIn:resourceList];
  323.         [self  checkFiles:&epsf.resources[RES_FILES]  placeIn:resourceList];
  324.         [self  checkProcSets:&epsf.resources[RES_PROCSETS]  placeIn:resourceList];
  325.         [self  checkPatterns:&epsf.resources[RES_PATTERNS]  placeIn:resourceList];
  326.         [self  checkForms:&epsf.resources[RES_FORMS]  placeIn:resourceList];
  327.  
  328.         [self  writeIncludedFiles:epsf.inclusions];
  329.  
  330.         return self;
  331.     }
  332.     else
  333.         Notify("Import Error", ErrorEpsf(error));
  334.  
  335.     return nil;
  336. }
  337.  
  338. /*
  339. *    Used when printing. Add the resources used in this file
  340. *    to the list passed in. Only adds the resources that are not
  341. *    currently in the resourceDoc structure already.
  342. */
  343. - addResources:(Resource *) resourceDoc  forFile:(NXAtom) fileName
  344. {
  345.     id            name;
  346.  
  347.     int            i, j, k, count;
  348.  
  349.     EpsfStruct    epsf;
  350.  
  351.     if (_fileName || fileName)
  352.     {
  353.         i = RES_SUPPLIED;
  354.         if (_fileName)
  355.         {
  356.             name = (id) _fileName;
  357.             if (NXDrawingStatus == NX_COPYING)
  358.                 i = RES_NEEDED;
  359.         }
  360.         else
  361.             name = (id) fileName;
  362.  
  363.         if (!resourceDoc[RES_FILES].states[RES_PRESENT])
  364.             resourceDoc[RES_FILES].states[RES_PRESENT] = [List  new];
  365.         if (!resourceDoc[RES_FILES].states[RES_NEEDED])
  366.             resourceDoc[RES_FILES].states[i] = [List  new];
  367.  
  368.         [resourceDoc[RES_FILES].states[RES_PRESENT]  addObjectIfAbsent:name];
  369.         [resourceDoc[RES_FILES].states[i]  addObjectIfAbsent:name];
  370.     }
  371.  
  372.     [self  getResources:&epsf];
  373.     for (i = 0; i < RES_NUMTYPES; i++)
  374.     {
  375.         for (j = 0; j < RES_NUMSTATES; j++)
  376.         {
  377.             if (epsf.resources[i].states[j])
  378.             {
  379.                 if (!resourceDoc[i].states[j])
  380.                     resourceDoc[i].states[j] = [List  new];
  381.  
  382.                 count = [epsf.resources[i].states[j]  count];
  383.                 for (k = 0; k < count; k++)
  384.                     [resourceDoc[i].states[j]
  385.                             addObjectIfAbsent:[epsf.resources[i].states[j]  objectAt:k]];
  386.             }
  387.         }
  388.     }
  389.     
  390.     return self;
  391. }
  392.  
  393. /*
  394. *    Overridden to handle any %%IncludeFile. A temporary file or
  395. *    memory buffer has been written out that adds the included
  396. *    files. This temporary file or memory pointer are swapped for the
  397. *    real ones if they exist. The image is drawn and then they are
  398. *    returned back. Their is probably a better way but without 
  399. *    knowing the internals of how this class works its a tenuous
  400. *    bet to find one.
  401. */
  402. - (BOOL) draw
  403. {
  404.     BOOL    rc = YES;
  405.  
  406.     char        *data,
  407.             *tempname,
  408.             *tempmemory;
  409.  
  410.     int        templen, len, maxlen;
  411.  
  412.     NXStream    *stream;
  413.  
  414.     templen = 0;
  415.     tempname = tempmemory = NULL;
  416.     if (_tempName || _tempMemory)
  417.     {
  418.         if (_fileName)
  419.         {
  420.             tempname = _fileName;
  421.             _fileName = _tempName;
  422.         }
  423.         else
  424.         {
  425.             tempmemory = _memory;
  426.             templen = _epsLen;
  427.             _memory = _tempMemory;
  428.             _epsLen = _tempEpsLen;
  429.         }
  430.     }
  431.     
  432.     /*************************************************************
  433.     *    The first case of the if-else statement is only to show
  434.     *    what can happen when a separate context is not used.
  435.     *    The imaging should be done with the draw method
  436.     *    because it installs a separate context.
  437.     **************************************************************/
  438.     if (![NXApp  contextFlag])
  439.     {
  440.         PStranslate(-_bBoxOrigin.x, -_bBoxOrigin.y);
  441.         if (_fileName && !_repFlags.dataLoaded)
  442.         {
  443.             stream = NXMapFile(_fileName, NX_READONLY);
  444.             if (stream)
  445.                 NXGetMemoryBuffer(stream, &data, &len, &maxlen);
  446.         }
  447.         else
  448.         {
  449.             data = _memory;
  450.             len = _epsLen;
  451.         }
  452.  
  453.         PSWBeginEpsf();
  454.         DPSWritePostScript(DPSGetCurrentContext(), data, len);
  455.         PSWEndEpsf();
  456.     }
  457.     else
  458.         rc = [super  draw];
  459.  
  460.     if (_tempName || _tempMemory)
  461.     {
  462.         if (_fileName)
  463.         {
  464.             _fileName = tempname;
  465.         }
  466.         else
  467.         {
  468.             _memory = tempmemory;
  469.             _epsLen = templen;
  470.         }
  471.     }
  472.  
  473.     return rc;
  474. }
  475.  
  476. /*
  477.  *    Draws the EPS file. Positions it appropriately, scaling and rotating
  478.  *    it according to the arguments passed in. The rotation is in degrees.
  479.  */
  480. - (BOOL) drawIn:(NXRect *) r  with:(float) rotation
  481. {
  482.     BOOL        error;
  483.  
  484.     NXRect        original;
  485.  
  486.     error = NO;
  487.     if (NXDrawingStatus == NX_COPYING)
  488.     {
  489.         original.origin = _bBoxOrigin;
  490.         original.size = size;
  491.         if (_fileName)
  492.         {
  493.             WriteEpsfIllustratorBeg(r, &original, rotation, _fileName);
  494.             WriteEpsfIllustratorInclude(_fileName);
  495.             WriteEpsfIllustratorEnd();
  496.         }
  497.         else
  498.         {
  499.             WriteEpsfIllustratorBeg(r, &original, rotation, NULL);
  500.             DPSWritePostScript(DPSGetCurrentContext(), _memory, _epsLen);
  501.             WriteEpsfIllustratorEnd();
  502.         }
  503.     }
  504.     else
  505.     {
  506.         PSgsave();
  507.         PStranslate(r->origin.x, r->origin.y);
  508.         PSrotate(rotation);
  509.         PSscale(r->size.width/size.width, r->size.height/size.height);
  510.         
  511.         error = [self  draw];
  512.         PSgrestore();
  513.     }
  514.  
  515.     return error;
  516. }
  517.  
  518. @end
  519.